
#ifndef _OGL_GRAPHICS_H_
#define _OGL_GRAPHICS_H_

#include "graphics/graphics.h"


class oglVertexBuffer;
class oglIndexBuffer;
class oglIBSet;
class oglVBSet;
class OglGraphics : public Graphics
{
public:
	
#ifdef _OPENGLES2
	static unsigned int		m_EGLProgram;
#endif

	// instantiate the graphics driver
	static void		Create();
	static void		Delete();

					OglGraphics();
	virtual			~OglGraphics();

	virtual	bool	Init();
	virtual bool	InitWindow(unsigned int Width, unsigned int Height, bool Fullscreen, bool EnableDebug = false);
	virtual void	RegisterFormats();
	virtual void*	GetDeviceDriver() const { return NULL;	};
	virtual void*	GetFlashDriver(); 

	virtual void	GetBestWideScreenRes(unsigned int& Width, unsigned int& Height, bool bGetForBackbuffer = true);

	virtual	bool	Shutdown();
	virtual	bool	ShutdownWindow();
	virtual	bool	Resize(unsigned int Width, unsigned int Height);
	virtual bool	ResetWindow(unsigned int Width, unsigned int Height, bool Fullscreen);

	// begin and end scene
	virtual bool	BeginScene();
	virtual void	EndScene();
	virtual void	Clear(COLOR c, float Depth = 1.0f, int Stencil = 0, bool ClearRGB = true, bool ClearDepth= true, bool ClearStencil= true);
	virtual bool	Present();


	// initialize internals for usual 2D and 3D options
	virtual void	Start2D();
	virtual void	Start3D(){};

	// texture stage stuff
	virtual void	SetTexStage(unsigned int TexStage, STAGE_TYPE type, BLEND_OP Op);
	virtual void	SetRenderState(RENDER_STATE r, unsigned int val);
	virtual void	SetTexture(unsigned int Stage, Image* pImg);

	// transforms
	virtual void	SetTransform(TRANSFORM_STAGE ts, const math::Mat4x4 & mat);
	virtual void	SetViewport(const math::Viewport& vp);

	// simplified draws.
	// 2D:
	virtual void	DrawVertex2D(Vertex2D*	VertA, unsigned int VertC, PRIMITIVE_TYPE Type = PT_TRI_LIST);
	virtual void	DrawIndexVertex2D(Vertex2D*	VertA, unsigned int VertC, unsigned short* IndexA, unsigned int IndexC, PRIMITIVE_TYPE Type = PT_TRI_LIST);
	virtual void	DrawFatIndexVertex2D(FatVertex2D*	VertA, unsigned int VertC, unsigned short* IndexA, unsigned int IndexC, PRIMITIVE_TYPE Type = PT_TRI_LIST){};

	virtual void	DrawVertex3D(Vertex3D*	VertA, unsigned int VertC, PRIMITIVE_TYPE Type = PT_TRI_LIST){};
	virtual void	DrawIndexVertex3D(Vertex3D*	VertA, unsigned int VertC, unsigned short* IndexA, unsigned int IndexC, PRIMITIVE_TYPE Type = PT_TRI_LIST){};

	// accessors
    unsigned short   GetScreenWidth() const { return m_ScreenWidth; };
    unsigned short   GetScreenHeight() const { return m_ScreenHeight; };
	static Graphics* GetGraphics() { return s_pGraphics; };

	// images
	virtual Image*	LoadImageFromFile(const std::string& Name);
	virtual Image*	LoadImageFromMemory(unsigned char* pData, unsigned int	Size);
	virtual Image*	CreateDynamicImage(unsigned short Width = 256, unsigned short Height= 256, unsigned short Depth=32);
	virtual Font*	CreateTTFFont(const std::string& Name);
	virtual AVI*	LoadMovie(const std::string& Name);
	virtual void	DestroyMovie(AVI* pAVI);
	virtual ImageCache*		CreateCache(int Width, int Height, int Depth);
	
	virtual void		SetFilter2D(bool b);
	virtual Image*		CreateComposite(int	width, int height, int depth, const std::vector<ImageLayer>& Layers);	
	
	
	oglVertexBuffer*		GetTempVB(int VertC);
	oglIndexBuffer*			GetTempIB(int IndexC);

private:
		
	bool				MapPrimitiveToOGL(PRIMITIVE_TYPE Type, unsigned int& GLMode , unsigned int VertC, unsigned int& PrimitiveC);
	
	//SOME OPTIMIZATIONS
	//current texture
	Image*				m_pCurTexture[2];
	unsigned int		m_CurRenderStates[Graphics::RENDER_STATE_C]; 
	BLEND_OP			m_CurTextureStates[2][Graphics::STAGE_TYPE_COUNT]; 

	std::vector<oglVBSet*>	m_VBSets;
	std::vector<oglIBSet*>	m_IBSets;

	
};


OglGraphics*	GetOGLGraphics();

#endif // _ogl_GRAPHICS_H_